package ar.com.larreta.comunes;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;


public class Transformador {
	
	private static Map<Class, Class> relaciones = new HashMap<Class, Class>();
	
	private Map copiados;
	
	public Transformador(){
		copiados = new HashMap();
	}
	
	private Transformador(String ruta){
		copiados = new HashMap();
		agregarTiposTipicos();
		
		Propiedades propiedades = new Propiedades(ruta);
		Iterator it = propiedades.keySet().iterator();
		while (it.hasNext()) {
			String clase = (String) it.next();
			Class claseA = Herramientas.getClase(clase);
			Class claseB = Herramientas.getClase(propiedades.getProperty(clase));
			relaciones.put(claseA, claseB);
			relaciones.put(claseB, claseA);
		}
	}

	/**
	 * Invoca al constructor privado que se encarga de inicializar los tipos a transformar
	 * @param ruta
	 */
	public static void inicializar (String ruta){
		new Transformador(ruta);
	}

	private void agregarTiposTipicos() {
		relaciones.put(String.class, String.class);
		relaciones.put(Integer.class, Integer.class);
		relaciones.put(Double.class, Double.class);
		relaciones.put(Long.class, Long.class);
		relaciones.put(Date.class, Date.class);
		relaciones.put(Set.class, HashSet.class);
		relaciones.put(Collection.class, ArrayList.class);
		relaciones.put(HashSet.class, HashSet.class);
		relaciones.put(ArrayList.class, ArrayList.class);
	}
	
	public static Class getClaseRelacionada(Class clase){
		if (relaciones.get(clase)!=null){
			return relaciones.get(clase);
		}
		return relaciones.get(clase.getSuperclass());
	}
	
	/**
	 * Transforma el objeto de vista a persistencia o biceversa
	 * @param viejo
	 * @return
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public Object getObjetoNuevo(Object viejo) throws InstantiationException, IllegalAccessException{
		Object nuevo = null;
		if (viejo!=null){
			if (copiados.get(viejo)==null) {
				Class relacionada = getClaseRelacionada(viejo.getClass());
				if (relacionada!=null){
					nuevo = relacionada.newInstance();
					copiados.put(viejo, nuevo);
					copiarPropiedades(viejo, nuevo);
				}
			} else {
				nuevo = copiados.get(viejo);
			}
		}
		return nuevo;
	}
	
	/**
	 * Retorna el clon de un objeto pasado por parametro
	 * @param viejo
	 * @return
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public Object clonar(Object viejo) throws InstantiationException, IllegalAccessException{
		Transformador transformador = new Transformador();
		return transformador.getObjetoNuevo(getObjetoNuevo(viejo));
	}
	
	private void copiarPropiedades(Object origen, Object destino) {
		DescriptorDeObjeto descriptorOrigen = Descriptores.getInstancia().getDescriptorDeObjeto(origen, this);
		DescriptorDeObjeto descriptorDestino = Descriptores.getInstancia().getDescriptorDeObjeto(destino, this);
		
		descriptorOrigen.copiar(descriptorDestino);
	}
	
}
